from flask import Blueprint, request, current_app
from marshmallow import ValidationError

from config.database import db
from models.account import Account, account_schema
from utils.res_result import make_response
from utils.role_required import role_required
from models.role import Role
from models.association_tables import account_role
import uuid

account_blueprint = Blueprint('account', __name__)


@account_blueprint.route('/accounts')
@role_required(role='ADMIN')
def index():
    page_num = request.args.get('page', 1, type=int)
    page_size = request.args.get('pageSize', 20, type=int)
    username = request.args.get('username', '', type=str)
    name = request.args.get('name', '', type=str)
    role_id = request.args.get('roleId', '', type=str)  # 添加role_id参数
    enabled = request.args.get('enabled', '', type=str)

    query = Account.query

    # 如果有role_id过滤，添加join和filter
    if role_id:
        query = query.join(account_role).join(Role).filter(Role.id == role_id)    

    if username:
        query = query.filter(Account.username.like(f'%{username}%'))
    if name:
        query = query.filter(Account.name.like(f'%{name}%'))
    # if role:
    #     query = query.filter(Account.role == role)
    if enabled:
        query = query.filter(Account.enabled == enabled)

    pagination = query.order_by(Account.username).paginate(page=page_num,
                                                           per_page=page_size,
                                                           error_out=False)
    accounts = pagination.items

    return make_response(data={
        "items": [account.to_dict() for account in accounts],
        "total": pagination.total
    })


@account_blueprint.route('/', methods=['POST'])
@role_required(role='ADMIN')
def add_account():
    try:
        data = request.get_json()
        data['enabled'] = '1'
        # data['password'] = '123456'
        # del data['dept']
        current_app.logger.info(data)
        account = account_schema.load(data)
        account.hash_password()
        role_id = data['roleId']

        existing_account = Account.query.filter(Account.username == account.username).first()
        if existing_account:
            return make_response(code=1, message="Username already exists", status=400)

        account.created_at = account.updated_at = db.func.now()
        db.session.add(account)
        db.session.flush()  # 这会让SQLAlchemy生成id而不实际提交到数据库

        account_role_record = {
            'id': str(uuid.uuid4()),
            'account_id': account.id,
            'role_id': role_id
        }
        db.session.execute(account_role.insert().values(**account_role_record))

        db.session.commit()
        return make_response()
    except ValidationError as err:
        current_app.logger.error(err.messages)
        return make_response(code=1, message="Field validation failed", status=400)
    finally:
        db.session.close()


@account_blueprint.route('/<string:account_id>', methods=['PUT'])
@role_required(role='ADMIN')
def edit_account(account_id):
    try:
        data = request.get_json()
        current_app.logger.info(data)
        
        # 获取role_id
        role_id = data.get('roleId')

        account = Account.query.get_or_404(account_id)

        existing_account = Account.query.filter(Account.username == data['username'],
                                                Account.id != account_id).first()
        if existing_account:
            return make_response(code=1, message="Username already exists", status=400)

        account_schema.load(data, instance=account, partial=True)

        if role_id:
            # 先删除旧的关联
            db.session.execute(
                account_role.delete().where(account_role.c.account_id == account_id)
            )
            
            # 插入新的关联
            account_role_record = {
                'id': str(uuid.uuid4()),
                'account_id': account_id,
                'role_id': role_id
            }
            db.session.execute(account_role.insert().values(**account_role_record))

        db.session.commit()
        return make_response()
    except ValidationError as err:
        current_app.logger.error(err.messages)
        return make_response(code=1, message="Field validation failed", status=400)
    finally:
        db.session.close()


@account_blueprint.route('/set_account_status', methods=['POST'])
@role_required(role='ADMIN')
def set_account_status():
    try:
        data = request.get_json()
        account_id = data.get('id')
        new_status = data.get('enabled')

        current_app.logger.info('account_id: %s, new_status: %s', account_id, new_status)

        if new_status not in ['0', '1']:
            return make_response(code=1, message="Invalid status value", status=400)

        account = Account.query.get_or_404(account_id)
        account.enabled = new_status
        db.session.commit()

        return make_response()

    except ValidationError as err:
        return make_response(code=1, message="Field validation failed", status=400)
    finally:
        db.session.close()


@account_blueprint.route('/<string:account_id>', methods=['DELETE'])
@role_required(role='ADMIN')
def delete_account(account_id):
    try:
        account = Account.query.get_or_404(account_id)
        db.session.delete(account)
        db.session.commit()
        return make_response()
    except ValidationError as err:
        return make_response(code=1, message="Field validation failed", status=400)
    finally:
        db.session.close()


@account_blueprint.route('/accountExist', methods=['POST'])
@role_required(role='ADMIN')
def account_exist():
    username = request.json.get('username')
    account_id = request.json.get('accountId', None)

    if account_id:
        count = Account.query.filter(Account.username == username, Account.id != account_id).count()
    else:
        count = Account.query.filter(Account.username == username).count()

    return make_response(data={"count": count})


@account_blueprint.route('/roles')
@role_required("ADMIN")
def roles():
    roles = Role.query.filter(Role.status == '1').order_by(Role.role_name).all()
    
    return make_response(data=[role.to_dict() for role in roles])